

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=auto>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/img/favicon.png">
  <link rel="icon" href="/img/favicon.png">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="author" content="John Doe">
  <meta name="keywords" content="">
  
    <meta name="description" content="简介awk 是一个强大的文本分析工具，相对于 grep 的查找，sed 的编辑，awk 在其对数据分析并生成报告时，显得尤为强大。简单来说 awk 就是把文件逐行的读入，以空格为默认分隔符将每行切片，切开的部分再进行各种分析处理。 使用方法1awk &amp;#x27;&amp;#123;pattern + action&amp;#125;&amp;#x27; &amp;#123;filenames&amp;#125; 其中 pattern 表">
<meta property="og:type" content="article">
<meta property="og:title" content="【转】shell-文本处理利器 awk">
<meta property="og:url" content="http://example.com/2019/05/29/shell/shell-%E6%96%87%E6%9C%AC%E5%A4%84%E7%90%86%E5%88%A9%E5%99%A8%20awk/index.html">
<meta property="og:site_name" content="Hexo">
<meta property="og:description" content="简介awk 是一个强大的文本分析工具，相对于 grep 的查找，sed 的编辑，awk 在其对数据分析并生成报告时，显得尤为强大。简单来说 awk 就是把文件逐行的读入，以空格为默认分隔符将每行切片，切开的部分再进行各种分析处理。 使用方法1awk &amp;#x27;&amp;#123;pattern + action&amp;#125;&amp;#x27; &amp;#123;filenames&amp;#125; 其中 pattern 表">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2019-05-29T05:26:35.000Z">
<meta property="article:modified_time" content="2022-02-10T03:11:01.439Z">
<meta property="article:author" content="John Doe">
<meta property="article:tag" content="Linux">
<meta property="article:tag" content="Shell">
<meta name="twitter:card" content="summary_large_image">
  
  
  <title>【转】shell-文本处理利器 awk - Hexo</title>

  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4/dist/css/bootstrap.min.css" />


  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@4/github-markdown.min.css" />
  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/hint.css@2/hint.min.css" />

  
    
    
      
      <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@10/styles/github-gist.min.css" />
    
  

  
    <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3/dist/jquery.fancybox.min.css" />
  


<!-- 主题依赖的图标库，不要自行修改 -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_ba1fz6golrf.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_lbnruvf0jn.css">


<link  rel="stylesheet" href="/css/main.css" />

<!-- 自定义样式保持在最底部 -->


  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    var CONFIG = {"hostname":"example.com","root":"/","version":"1.8.13","typing":{"enable":true,"typeSpeed":70,"cursorChar":"_","loop":false},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"right","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"copy_btn":true,"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":0},"lazyload":{"enable":true,"loading_img":"/img/loading.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":false,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"app_id":null,"app_key":null,"server_url":null,"path":"window.location.pathname","ignore_local":false}},"search_path":"/local-search.xml"};
  </script>
  <script  src="/js/utils.js" ></script>
  <script  src="/js/color-schema.js" ></script>
<meta name="generator" content="Hexo 6.0.0"></head>


<body>
  <header style="height: 70vh;">
    <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand" href="/">
      <strong>LZDF</strong>
    </a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/">
                <i class="iconfont icon-home-fill"></i>
                首页
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/archives/">
                <i class="iconfont icon-archive-fill"></i>
                归档
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/categories/">
                <i class="iconfont icon-category-fill"></i>
                分类
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/tags/">
                <i class="iconfont icon-tags-fill"></i>
                标签
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/about/">
                <i class="iconfont icon-user-fill"></i>
                关于
              </a>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" target="_self" href="javascript:;" data-toggle="modal" data-target="#modalSearch" aria-label="Search">
              &nbsp;<i class="iconfont icon-search"></i>&nbsp;
            </a>
          </li>
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" target="_self" href="javascript:;" aria-label="Color Toggle">&nbsp;<i
                class="iconfont icon-dark" id="color-toggle-icon"></i>&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

    <div class="banner" id="banner" parallax=true
         style="background: url('/img/default.png') no-repeat center center;
           background-size: cover;">
      <div class="full-bg-img">
        <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
          <div class="page-header text-center fade-in-up">
            <span class="h2" id="subtitle" title="【转】shell-文本处理利器 awk">
              
            </span>

            
              <div class="mt-3">
  
  
    <span class="post-meta">
      <i class="iconfont icon-date-fill" aria-hidden="true"></i>
      <time datetime="2019-05-29 13:26" pubdate>
        2019年5月29日 下午
      </time>
    </span>
  
</div>

<div class="mt-1">
  
    <span class="post-meta mr-2">
      <i class="iconfont icon-chart"></i>
      16k 字
    </span>
  

  
    <span class="post-meta mr-2">
      <i class="iconfont icon-clock-fill"></i>
      
      
      133 分钟
    </span>
  

  
  
</div>

            
          </div>

          
        </div>
      </div>
    </div>
  </header>

  <main>
    
      

<div class="container-fluid nopadding-x">
  <div class="row nomargin-x">
    <div class="d-none d-lg-block col-lg-2"></div>
    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div class="py-5" id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">【转】shell-文本处理利器 awk</h1>
            
            <div class="markdown-body">
              <h1 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h1><p><code>awk</code> 是一个强大的文本分析工具，相对于 <code>grep</code> 的查找，<code>sed</code> 的编辑，<code>awk</code> 在其对数据分析并生成报告时，显得尤为强大。简单来说 <code>awk</code> 就是把文件逐行的读入，以空格为默认分隔符将每行切片，切开的部分再进行各种分析处理。</p>
<h1 id="使用方法"><a href="#使用方法" class="headerlink" title="使用方法"></a>使用方法</h1><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">awk <span class="hljs-string">&#x27;&#123;pattern + action&#125;&#x27;</span> &#123;filenames&#125;<br></code></pre></td></tr></table></figure>
<p>其中 <code>pattern</code> 表示 <strong>awk</strong> 在数据中查找的内容，而 <code>action</code> 是在找到匹配内容时所执行的一系列命令。花括号（{}）不需要在程序中始终出现，但它们用于根据特定的模式对一系列指令进行分组。<code>pattern</code> 就是要表示的正则表达式，用斜杠括起来。</p>
<p><strong>awk</strong> 语言的最基本功能是在文件或者字符串中基于指定规则浏览和抽取信息，<strong>awk</strong>抽取信息后，才能进行其他文本操作。完整的<strong>awk</strong>脚本通常用来格式化文本文件中的信息。</p>
<p>通常，<strong>awk</strong>是以文件的一行为处理单位的。<strong>awk</strong>每接收文件的一行，然后执行相应的命令，来处理文本。</p>
<h2 id="调用-awk"><a href="#调用-awk" class="headerlink" title="调用 awk"></a>调用 awk</h2><p>有三种方式调用 <code>awk</code></p>
<ul>
<li>命令行方式</li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">awk [-F  field-separator]  <span class="hljs-string">&#x27;commands&#x27;</span>  input-file(s)<br>其中，commands 是真正awk命令，[-F域分隔符]是可选的。 input-file(s) 是待处理的文件。<br>在awk中，文件的每一行中，由域分隔符分开的每一项称为一个域。通常，在不指名-F域分隔符的情况下，默认的域分隔符是空格。<br></code></pre></td></tr></table></figure>

<ul>
<li>shell 脚本方式</li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">将所有的awk命令插入一个文件，并使awk程序可执行，然后awk命令解释器作为脚本的首行，一遍通过键入脚本名称来调用。<br>相当于shell脚本首行的：<span class="hljs-comment">#!/bin/sh</span><br>可以换成：<span class="hljs-comment">#!/bin/awk</span><br></code></pre></td></tr></table></figure>

<ul>
<li>将所有 awk 命令插入一个单独文件，然后调用</li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">awk -f awk-script-file input-file(s)<br>其中，-f选项加载awk-script-file中的awk脚本，input-file(s)跟上面的是一样的。<br></code></pre></td></tr></table></figure>

<h2 id="实例"><a href="#实例" class="headerlink" title="实例"></a>实例</h2><p><strong>显示登录账户信息</strong></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ last -n 5	<span class="hljs-comment"># 列出最近 5 条目前与过去登入系统的用户相关信息</span><br>aurora   tty1         :0               Mon May 27 08:44   still logged <span class="hljs-keyword">in</span><br>reboot   system boot  4.15.0-29deepin- Mon May 27 08:29   still running<br>aurora   tty1         :0               Tue May 21 08:40 - down  (3+09:23)<br>reboot   system boot  4.15.0-29deepin- Tue May 21 08:40 - 18:03 (3+09:23)<br>aurora   tty1         :0               Mon May 20 08:52 - crash  (23:47)<br>$ last -n 5 | awk <span class="hljs-string">&#x27;&#123;print $1&#125;&#x27;</span> <span class="hljs-comment"># 只显示最近登录的 5 个账号</span><br>aurora<br>reboot<br>aurora<br>reboot<br>aurora<br></code></pre></td></tr></table></figure>
<p><code>awk</code> 工作流程是这样的：读入有 ‘\n’ 换行符分割的一条记录，然后将记录按指定的域分隔符划分域，填充域，<code>$0</code> 则表示所有域， <code>$1</code>表示第一个域，<code>$n</code>表示第n个域。默认域分隔符是”空白键” 或 “[tab]键”,所以 <code>$1</code> 表示登录用户，<code>$3</code> 表示登录用户ip，以此类推。</p>
<p><strong>显示‘/etc/passwd’账户</strong></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ cat /etc/passwd | awk -F <span class="hljs-string">&#x27;:&#x27;</span> <span class="hljs-string">&#x27;&#123;print $1&#125;&#x27;</span><br>root<br>daemon<br>bin<br>sys<br>sync<br>......<br></code></pre></td></tr></table></figure>

<p>这种是 <code>awk+action</code> 的示例，每行都执行 <code>action&#123;print $1&#125;</code>。<code>-F</code> 指定域分隔符为’:’。</p>
<p><strong>只显示’/etc/passwd‘的账户和对应的shell</strong></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ cat /etc/passwd | awk -F <span class="hljs-string">&#x27;:&#x27;</span> <span class="hljs-string">&#x27;&#123;print $1&quot;\t&quot;$7&#125;&#x27;</span><br>root	/bin/bash<br>daemon	/usr/sbin/nologin<br>bin	/usr/sbin/nologin<br>sys	/usr/sbin/nologin<br>sync	/bin/sync<br>......<br>$ cat /etc/passwd | awk -F <span class="hljs-string">&#x27;:&#x27;</span> <span class="hljs-string">&#x27;BEGIN &#123;print &quot;name,shell&quot;&#125; &#123;print $1&quot;,&quot;$7&#125; END &#123;print &quot;blue,/bin/nosh&quot;&#125;&#x27;</span><br>name,shell<br>root,/bin/bash<br>daemon,/usr/sbin/nologin<br>bin,/usr/sbin/nologin<br>sys,/usr/sbin/nologin<br>sync,/bin/sync<br>......<br>blue,/bin/nosh<br></code></pre></td></tr></table></figure>

<p>第二条命令的作用是：只是显示 <code>/etc/passwd</code> 的账户和账户对应的 shell，而账户与 shell 之间以逗号分割，而且在所有行添加列名 name、shell，在最后一行添加 “blue,/bin/nosh”。</p>
<p><strong>awk</strong> 工作流程是这样的：先执行 <strong>BEGIN</strong>，然后读取文件，读入有 <code>/n</code> 换行符分割的一条记录，然后将记录按指定的域分隔符划分域，填充域，*$0 则表示所有域*, <em>$1 表示第一个域，</em><em>$n表示第n个域</em>，随后开始执行模式所对应的动作 action。接着开始读入第二条记录······直到所有的记录都读完，最后执行END操作。</p>
<p><strong>搜索‘/etc/passwd’有 root 关键字的所有行</strong></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ awk -F <span class="hljs-string">&#x27;:&#x27;</span> <span class="hljs-string">&#x27;/root/&#x27;</span> /etc/passwd <span class="hljs-comment"># 打印匹配正则的所有行</span><br>root:x:0:0:root:/root:/bin/bash<br>......<br>$ awk -F <span class="hljs-string">&#x27;:&#x27;</span> <span class="hljs-string">&#x27;/root/&#123;print $7&#125;&#x27;</span> /etc/passwd <span class="hljs-comment"># 打印匹配正则的 $7 参数</span><br>/bin/bash<br>......<br></code></pre></td></tr></table></figure>

<p>1）这种是 <strong>pattern</strong> 的使用示例，匹配了 <strong>pattern</strong> (这里是root)的行才会执行 <strong>action</strong> (没有指定action，默认输出每行的内容)。</p>
<p>搜索支持正则，例如找 ’root‘ 开头的：<code> awk -F: &#39;/^root/&#39; /etc/passwd</code> </p>
<p>2）这里指定了 <strong>action</strong> ：<code>&#123;print $7&#125;</code></p>
<h1 id="awk内置变量"><a href="#awk内置变量" class="headerlink" title="awk内置变量"></a>awk内置变量</h1><p>awk有许多内置变量用来设置环境信息，这些变量可以被改变，下面给出了最常用的一些变量。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs bash">ARGC               命令行参数个数<br>ARGV               命令行参数排列<br>ENVIRON            支持队列中系统环境变量的使用<br>FILENAME           awk浏览的文件名<br>FNR                浏览文件的记录数<br>FS                 设置输入域分隔符，等价于命令行 -F选项<br>NF                 浏览记录的域的个数<br>NR                 已读的记录数<br>OFS                输出域分隔符<br>ORS                输出记录分隔符<br>RS                 控制记录分隔符<br></code></pre></td></tr></table></figure>

<p> 此外,$0变量是指整条记录。$1表示当前行的第一个域，$2表示当前行的第二个域，……以此类推。</p>
<p><strong>统计‘/etc/passwd’：文件名，每行的行号，每行的列数，对应的完整行内容</strong>:</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ awk  -F <span class="hljs-string">&#x27;:&#x27;</span>  <span class="hljs-string">&#x27;&#123;print &quot;filename:&quot; FILENAME &quot;,linenumber:&quot; NR &quot;,columns:&quot; NF &quot;,linecontent:&quot;$0&#125;&#x27;</span> /etc/passwd<br>filename:/etc/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/bash<br>filename:/etc/passwd,linenumber:2,columns:7,linecontent:daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin<br>filename:/etc/passwd,linenumber:3,columns:7,linecontent:bin:x:2:2:bin:/bin:/usr/sbin/nologin<br>filename:/etc/passwd,linenumber:4,columns:7,linecontent:sys:x:3:3:sys:/dev:/usr/sbin/nologin<br>filename:/etc/passwd,linenumber:5,columns:7,linecontent:sync:x:4:65534:sync:/bin:/bin/sync<br>......<br>$  awk  -F <span class="hljs-string">&#x27;:&#x27;</span>  	<span class="hljs-string">&#x27;&#123;printf(&quot;filename:%10s,linenumber:%s,columns:%s,linecontent:%s\n&quot;,FILENAME,NR,NF,$0)&#125;&#x27;</span> /etc/passwd<br>filename:/etc/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/bash<br>filename:/etc/passwd,linenumber:2,columns:7,linecontent:daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin<br>filename:/etc/passwd,linenumber:3,columns:7,linecontent:bin:x:2:2:bin:/bin:/usr/sbin/nologin<br>filename:/etc/passwd,linenumber:4,columns:7,linecontent:sys:x:3:3:sys:/dev:/usr/sbin/nologin<br>filename:/etc/passwd,linenumber:5,columns:7,linecontent:sync:x:4:65534:sync:/bin:/bin/sync<br>......<br>$ awk -F <span class="hljs-string">&#x27;:&#x27;</span> <span class="hljs-string">&#x27;BEGIN&#123;print &quot;fileName, lineNumber, columns, content&quot;&#125;&#123;print FILENAME &quot;, &quot; NR &quot;, &quot; NF &quot;, &quot; $0&#125;&#x27;</span> /etc/passwd<br>fileName, lineNumber, columns, content<br>/etc/passwd, 1, 7, root:x:0:0:root:/root:/bin/bash<br>/etc/passwd, 2, 7, daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin<br>/etc/passwd, 3, 7, bin:x:2:2:bin:/bin:/usr/sbin/nologin<br>/etc/passwd, 4, 7, sys:x:3:3:sys:/dev:/usr/sbin/nologin<br>/etc/passwd, 5, 7, sync:x:4:65534:sync:/bin:/bin/sync<br>......<br></code></pre></td></tr></table></figure>

<p>使用 <code>printf</code> 替代 <code>print，</code>可以让代码更加简洁，易读（当然，使用 BEGIN 修饰的话，显示效果更好）。</p>
<h2 id="print和printf"><a href="#print和printf" class="headerlink" title="print和printf"></a><strong>print和printf</strong></h2><p><strong>awk</strong> 中同时提供了 <code>print</code> 和 <code>printf</code> 两种打印输出的函数。</p>
<p>其中 <code>print</code> 函数的参数可以是变量、数值或者字符串。<strong>字符串必须用双引号引用</strong>，<strong>参数用逗号分隔</strong>。如果没有逗号，参数就串联在一起而无法区分。这里，逗号的作用与输出文件的分隔符的作用是一样的，只是后者是空格而已。</p>
<p><code>printf</code> 函数，其用法和 c 语言中 printf 基本相似,可以格式化字符串,输出复杂时，<code>printf</code> 更加好用，代码更易懂。</p>
<h1 id="awk编程"><a href="#awk编程" class="headerlink" title="awk编程"></a>awk编程</h1><h2 id="变量和赋值"><a href="#变量和赋值" class="headerlink" title="变量和赋值"></a>变量和赋值</h2><p>除了 <strong>awk</strong> 的内置变量，<strong>awk</strong> 还可以自定义变量。</p>
<p>示例：统计 ‘/etc/passwd’ 的账户人数</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ awk <span class="hljs-string">&#x27;&#123;count++;print $0;&#125; END&#123;print &quot;user count is &quot;, count&#125;&#x27;</span> /etc/passwd<br>root:x:0:0:root:/root:/bin/bash<br>......<br>user count is  44<br></code></pre></td></tr></table></figure>

<p><code>count</code> 是自定义变量。之前的 <code>action&#123;&#125;</code> 里都是只有一个 <code>print,</code>其实 <code>print</code> 只是一个语句，而<strong>action{}可以有多个语句，以<code>;</code>号隔开</strong>。</p>
<p>这里没有初始化 <code>count</code>，虽然默认是0，但是妥当的做法还是初始化为0。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ awk <span class="hljs-string">&#x27;BEGIN &#123;count=0;print &quot;[start]user count is &quot;, count&#125; &#123;count=count+1;print $0;&#125; END&#123;print &quot;[end]user count is &quot;, count&#125;&#x27;</span> /etc/passwd<br>[start]user count is  0<br>root:x:0:0:root:/root:/bin/bash<br>......<br>[end]user count is  44<br></code></pre></td></tr></table></figure>

<p><strong>统计某个文件夹下的文件占用的字节数</strong></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ <span class="hljs-built_in">pwd</span> <br>/tmp<br>$ ls -l | awk <span class="hljs-string">&#x27;BEGIN &#123;size=0;&#125; &#123;size=size+$5;&#125; END&#123;print &quot;[end]size is &quot;, size&#125;&#x27;</span> <span class="hljs-comment"># 以 byte 为单位</span><br>[end]size is  340835<br>$ ls -l |awk <span class="hljs-string">&#x27;BEGIN &#123;size=0;&#125; &#123;size=size+$5;&#125; END&#123;print &quot;[end]size is &quot;, size/1024/1024,&quot;M&quot;&#125;&#x27;</span>  <span class="hljs-comment"># 以 M 为单位</span><br>[end]size is  0.325046 M<br></code></pre></td></tr></table></figure>

<p><em>注意，统计不包括文件夹的子目录。</em></p>
<h2 id="条件语句"><a href="#条件语句" class="headerlink" title="条件语句"></a>条件语句</h2><p><strong>awk</strong> 中的条件语句是从 C 语言中借鉴来的，见如下声明方式：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-keyword">if</span> (expression) &#123;<br>    statement;<br>    statement;<br>    ... ...<br>&#125;<br><br><span class="hljs-keyword">if</span> (expression) &#123;<br>    statement;<br>&#125; <span class="hljs-keyword">else</span> &#123;<br>    statement2;<br>&#125;<br><br><span class="hljs-keyword">if</span> (expression) &#123;<br>    statement1;<br>&#125; <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (expression1) &#123;<br>    statement2;<br>&#125; <span class="hljs-keyword">else</span> &#123;<br>    statement3;<br>&#125;<br></code></pre></td></tr></table></figure>

<p><strong>统计某个文件夹下的文件占用的字节数,过滤4096大小的文件(一般都是文件夹)</strong>:</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ <span class="hljs-built_in">pwd</span><br>/tmp<br>$ ls -l | awk <span class="hljs-string">&#x27;BEGIN &#123;size=0;print &quot;[start]size is &quot;, size&#125; &#123;if($5!=4096)&#123;size=size+$5&#125;&#125; END&#123;print &quot;[end size is ]&quot;, size/1024/1024, &quot;M&quot;&#125;&#x27;</span><br>[start]size is  0<br>[end size is ] 0.286259 M<br></code></pre></td></tr></table></figure>

<h2 id="循环语句"><a href="#循环语句" class="headerlink" title="循环语句"></a>循环语句</h2><p><strong>awk</strong>中的循环语句同样借鉴于 C 语言，支持 <code>while</code>、<code>do/while</code>、<code>for</code>、<code>break</code>、<code>continue</code>，这些关键字的语义和 C 语言中的语义完全相同。</p>
<h2 id="数组"><a href="#数组" class="headerlink" title="数组"></a>数组</h2><p>因为<strong>awk</strong>中数组的下标可以是数字和字母，数组的下标通常被称为关键字(key)。值和关键字都存储在内部的一张针对 <code>key/value</code> 应用<strong>hash</strong>的表格里。由于<strong>hash</strong>不是顺序存储，因此在显示数组内容时会发现，它们并不是按照你预料的顺序显示出来的。数组和变量一样，都是在使用时自动创建的，<strong>awk</strong>也同样会自动判断其存储的是数字还是字符串。一般而言，<strong>awk</strong>中的数组用来从记录中收集信息，可以用于计算总和、统计单词以及跟踪模板被匹配的次数等等。</p>
<p><strong>显示/etc/passwd的账户</strong></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ awk -F <span class="hljs-string">&#x27;:&#x27;</span> <span class="hljs-string">&#x27;BEGIN &#123;count=0;&#125; &#123;name[count] = $1;count++;&#125;; END&#123;for (i = 0; i &lt; NR; i++) print i, name[i]&#125;&#x27;</span> /etc/passwd<br>0 root<br>1 daemon<br>2 bin<br>3 sys<br>4 sync<br>......<br></code></pre></td></tr></table></figure>

<p><em>这里使用for循环遍历数组</em></p>
<p>awk编程的内容极多，这里只罗列简单常用的用法，更多请参考 <a target="_blank" rel="noopener" href="http://www.gnu.org/software/gawk/manual/gawk.html">http://www.gnu.org/software/gawk/manual/gawk.html</a></p>
<h2 id="重定向和管道"><a href="#重定向和管道" class="headerlink" title="重定向和管道"></a>重定向和管道</h2><ul>
<li><p>awk 可使用 shell 的重定向符进行重定向输出，如：<code>$ awk &#39;$1 = 100 &#123;print $1 &gt; &quot;output_file&quot; &#125;&#39; test</code>。上式表示如果第一个域的值等于100，则把它输出到output_file中。也可以用 <code>&gt;&gt;</code> 来重定向输出，但<strong>不清空文件，只做追加操作</strong>。</p>
</li>
<li><p>输出重定向需用到 <strong>getline</strong> 函数。<strong>getline</strong> 从标准输入、管道或者当前正在处理的文件之外的其他输入文件获得输入。它负责从输入获得下一行的内容，并给NF,NR和FNR等内建变量赋值。如果得到一条记录，<strong>getline</strong> 函数返回1，如果到达文件的末尾就返回0，如果出现错误，例如打开文件失败，就返回-1。如：</p>
<p><code>$ awk &#39;BEGIN&#123; &quot;date&quot; | getline d; print d&#125;&#39; test</code>。执行linux的date命令，并通过管道输出给 <strong>getline</strong>，然后再把输出赋值给自定义变量d，并打印它。</p>
<p><code>$ awk &#39;BEGIN&#123;&quot;date&quot; | getline d; split(d,mon); print mon[2]&#125;&#39; test</code>。执行shell的date命令，并通过管道输出给 <strong>getline</strong>，然后getline从管道中读取并将输入赋值给d，split函数把变量d转化成数组mon，然后打印数组mon的第二个元素。</p>
<p><code>$ awk &#39;BEGIN&#123;while( &quot;ls&quot; | getline) print&#125;&#39;</code>，命令 <code>ls</code> 的输出传递给 geline 作为输入，循环使getline从ls的输出中读取一行，并把它打印到屏幕。这里没有输入文件，因为 <strong>BEGIN</strong> 块在打开输入文件前执行，所以可以忽略输入文件。</p>
<p><code>$ awk &#39;BEGIN&#123;printf &quot;What is your name?&quot;; getline name &lt; &quot;/dev/tty&quot; &#125; $1 ~name &#123;print &quot;Found&quot; name on line &quot;, NR &quot;.&quot;&#125; END&#123;print &quot;See you,&quot; name &quot;.&quot;&#125; test</code>。在屏幕上打印”What is your name?”,并等待用户应答。当一行输入完毕后，getline函数从终端接收该行输入，并把它储存在自定义变量name中。如果第一个域匹配变量name的值，print函数就被执行，<strong>END</strong> 块打印See you和name的值。</p>
<p><code>$ awk &#39;BEGIN&#123;while (getline &lt; &quot;/etc/passwd&quot; &gt; 0) lc++; print lc&#125;&#39;</code>。awk将逐行读取文件/etc/passwd的内容，在到达文件末尾前，计数器lc一直增加，当到末尾时，打印lc的值。注意，如果文件不存在，getline返回-1，如果到达文件的末尾就返回0，如果读到一行，就返回1，所以命令 <code>while (getline &lt; &quot;/etc/passwd&quot;)</code>在文件不存在的情况下将陷入无限循环，因为返回-1表示逻辑真。</p>
</li>
<li><p>可以在awk中打开一个管道，且同一时刻只能有一个管道存在。通过close()可关闭管道。如：<code>$ awk &#39;&#123;print $1, $2 | &quot;sort&quot; &#125;&#39; test END &#123;close(&quot;sort&quot;)&#125;</code>。awd把print语句的输出通过管道作为linux命令sort的输入,END块执行关闭管道操作。</p>
</li>
<li><p><strong>system</strong>函数可以在awk中执行linux的命令。如：<code>$ awk &#39;BEGIN&#123;system(&quot;clear&quot;)&#39;</code>。</p>
</li>
<li><p><strong>fflush</strong>函数用以刷新输出缓冲区，如果没有参数，就刷新标准输出的缓冲区，如果以空字符串为参数，如<code>fflush(&quot;&quot;)</code>,则刷新所有文件和管道的输出缓冲区。</p>
</li>
</ul>
<h1 id="awk脚本"><a href="#awk脚本" class="headerlink" title="awk脚本"></a>awk脚本</h1><p>awk脚本是由<strong>模式</strong>和<strong>操作</strong>组成的：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">pattern &#123;action&#125; 如$ awk <span class="hljs-string">&#x27;/root/&#x27;</span> <span class="hljs-built_in">test</span>，或$ awk <span class="hljs-string">&#x27;$3 &lt; 100&#x27;</span> <span class="hljs-built_in">test</span>。<br></code></pre></td></tr></table></figure>

<p>两者是可选的，如果<strong>没有模式，则action应用到全部记录</strong>，如果<strong>没有action，则输出匹配全部记录</strong>。默认情况下，每一个输入行都是一条记录，但用户可通过<strong>RS</strong>变量指定不同的分隔符进行分隔。</p>
<h2 id="模式"><a href="#模式" class="headerlink" title="模式"></a>模式</h2><p>模式可以是以下任意一个：</p>
<ul>
<li>/正则表达式/：使用通配符的扩展集。</li>
<li>关系表达式：可以用下面运算符表中的关系运算符进行操作，可以是字符串或数字的比较，如$2&gt;%1选择第二个字段比第一个字段长的行。</li>
<li>模式匹配表达式：用运算符<del>(匹配)和</del>!(不匹配)。</li>
<li>模式，模式：<strong>指定一个行的范围</strong>。该语法不能包括BEGIN和END模式。</li>
<li>BEGIN：让用户指定<strong>在第一条输入记录被处理之前所发生的动作</strong>，通常可在这里设置全局变量。</li>
<li>END：让用户在最后一条输入记录被<strong>读取之后发生</strong>的动作。</li>
</ul>
<h2 id="操作"><a href="#操作" class="headerlink" title="操作"></a>操作</h2><p>操作由一人或多个命令、函数、表达式组成，之间由换行符或分号隔开，并<strong>位于大括号内</strong>。主要有四部份：</p>
<ul>
<li>变量或数组赋值</li>
<li>输出命令</li>
<li>内置函数</li>
<li>控制流命令</li>
</ul>
<h1 id="awk的环境变量"><a href="#awk的环境变量" class="headerlink" title="awk的环境变量"></a>awk的环境变量</h1><table>
<thead>
<tr>
<th align="left">变量</th>
<th>描述</th>
</tr>
</thead>
<tbody><tr>
<td align="left">$n</td>
<td>当前记录的第n个字段，字段间由FS分隔。</td>
</tr>
<tr>
<td align="left">$0</td>
<td>完整的输入记录。</td>
</tr>
<tr>
<td align="left">ARGC</td>
<td>命令行参数的数目。</td>
</tr>
<tr>
<td align="left">ARGIND</td>
<td>命令行中当前文件的位置(从0开始算)。</td>
</tr>
<tr>
<td align="left">ARGV</td>
<td>包含命令行参数的数组。</td>
</tr>
<tr>
<td align="left">CONVFMT</td>
<td>数字转换格式(默认值为%.6g)</td>
</tr>
<tr>
<td align="left">ENVIRON</td>
<td>环境变量关联数组。</td>
</tr>
<tr>
<td align="left">ERRNO</td>
<td>最后一个系统错误的描述。</td>
</tr>
<tr>
<td align="left">FIELDWIDTHS</td>
<td>字段宽度列表(用空格键分隔)。</td>
</tr>
<tr>
<td align="left">FILENAME</td>
<td>当前文件名。</td>
</tr>
<tr>
<td align="left">FNR</td>
<td>同NR，但相对于当前文件。</td>
</tr>
<tr>
<td align="left">FS</td>
<td>字段分隔符(默认是任何空格)。</td>
</tr>
<tr>
<td align="left">IGNORECASE</td>
<td>如果为真，则进行忽略大小写的匹配。</td>
</tr>
<tr>
<td align="left">NF</td>
<td>当前记录中的字段数。</td>
</tr>
<tr>
<td align="left">NR</td>
<td>当前记录数。</td>
</tr>
<tr>
<td align="left">OFMT</td>
<td>数字的输出格式(默认值是%.6g)。</td>
</tr>
<tr>
<td align="left">OFS</td>
<td>输出字段分隔符(默认值是一个空格)。</td>
</tr>
<tr>
<td align="left">ORS</td>
<td>输出记录分隔符(默认值是一个换行符)。</td>
</tr>
<tr>
<td align="left">RLENGTH</td>
<td>由match函数所匹配的字符串的长度。</td>
</tr>
<tr>
<td align="left">RS</td>
<td>记录分隔符(默认是一个换行符)。</td>
</tr>
<tr>
<td align="left">RSTART</td>
<td>由match函数所匹配的字符串的第一个位置。</td>
</tr>
<tr>
<td align="left">SUBSEP</td>
<td>数组下标分隔符(默认值是\034)。</td>
</tr>
</tbody></table>
<h1 id="awk运算符"><a href="#awk运算符" class="headerlink" title="awk运算符"></a>awk运算符</h1><table>
<thead>
<tr>
<th>运算符</th>
<th>描述</th>
</tr>
</thead>
<tbody><tr>
<td>= += -= *= /= %= ^= **=</td>
<td>赋值</td>
</tr>
<tr>
<td>?:</td>
<td>C条件表达式</td>
</tr>
<tr>
<td>||</td>
<td>逻辑或</td>
</tr>
<tr>
<td>&amp;&amp;</td>
<td>逻辑与</td>
</tr>
<tr>
<td>~ ~!</td>
<td>匹配正则表达式和不匹配正则表达式</td>
</tr>
<tr>
<td>&lt; &lt;= &gt; &gt;= != ==</td>
<td>关系运算符</td>
</tr>
<tr>
<td>空格</td>
<td>连接</td>
</tr>
<tr>
<td>+ -</td>
<td>加，减</td>
</tr>
<tr>
<td>* / &amp;</td>
<td>乘，除与求余</td>
</tr>
<tr>
<td>+ - !</td>
<td>一元加，减和逻辑非</td>
</tr>
<tr>
<td>^ ***</td>
<td>求幂</td>
</tr>
<tr>
<td>++ –</td>
<td>增加或减少，作为前缀或后缀</td>
</tr>
<tr>
<td>$</td>
<td>字段引用</td>
</tr>
<tr>
<td>in</td>
<td>数组成员</td>
</tr>
</tbody></table>
<h1 id="记录和域"><a href="#记录和域" class="headerlink" title="记录和域"></a>记录和域</h1><h2 id="记录"><a href="#记录" class="headerlink" title="记录"></a>记录</h2><p>awk把<strong>每一个以换行符结束的行称为一个记录</strong>。</p>
<p>记录分隔符：默认的输入和输出的分隔符都是<strong>回车</strong>，保存在内建变量<code>ORS</code>和<code>RS</code>中。</p>
<h2 id="域"><a href="#域" class="headerlink" title="域"></a>域</h2><p><strong>记录中每个单词称做“域”</strong>，默认情况下以空格或tab分隔。awk可跟踪域的个数，并在内建变量<code>NF</code>中保存该值。如$ awk ‘{print $1,$3}’ test将打印test文件中第一和第三个以空格分开的列(域)。</p>
<h2 id="域分隔符"><a href="#域分隔符" class="headerlink" title="域分隔符"></a>域分隔符</h2><p>内建变量<code>FS</code>保存输入域分隔符的值，默认是<em>空格 或 tab</em>。我们可以通过<code>-F</code>命令行选项修改<code>FS</code>的值。如<code>$ awk -F: &#39;&#123;print $1,$5&#125;&#39; test</code>将打印以冒号为分隔符的第一，第五列的内容。</p>
<p>可以同时使用多个域分隔符，这时应该把分隔符写成放到方括号中，如<code>$awk -F&#39;[:\t]&#39; &#39;&#123;print $1,$3&#125;&#39; test</code>，表示以空格、冒号和tab作为分隔符。</p>
<p>输出域的分隔符默认是一个空格，保存在<code>OFS</code>中。如<code>$ awk -F: &#39;&#123;print $1,$5&#125;&#39; test</code>，$1和$5间的逗号就是OFS的值。</p>
<h1 id="gawk专用正则表达式元字符"><a href="#gawk专用正则表达式元字符" class="headerlink" title="gawk专用正则表达式元字符"></a>gawk专用正则表达式元字符</h1><p>以下几个是gawk专用的，不适合unix版本的awk。</p>
<p>\Y    匹配一个单词开头或者末尾的空字符串。</p>
<p>\B    匹配单词内的空字符串。</p>
<p>\&lt;    匹配一个单词的开头的空字符串，锚定开始。</p>
<p>\&gt;    匹配一个单词的末尾的空字符串，锚定末尾。</p>
<p>\w    匹配一个字母数字组成的单词。</p>
<p>\W    匹配一个非字母数字组成的单词。</p>
<p>\‘    匹配字符串开头的一个空字符串。</p>
<p>\‘    匹配字符串末尾的一个空字符串。</p>
<h1 id="awk的内建函数"><a href="#awk的内建函数" class="headerlink" title="awk的内建函数"></a>awk的内建函数</h1><h2 id="字符串内建函数"><a href="#字符串内建函数" class="headerlink" title="字符串内建函数"></a>字符串内建函数</h2><ul>
<li><strong>sub</strong> 函数匹配记录中最大、最靠左边的子字符串正则表达式，并用替换字符串替换这些字符串。如果没有指定目标字符串就默认使用整个记录。替换只发生在第一次匹配的时候。格式如下：</li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">sub （regular expression, substitution string）:<br>sub (regular expression, substitution string, target string)<br></code></pre></td></tr></table></figure>

<p><strong>示例：</strong></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ awk <span class="hljs-string">&#x27;&#123;sub(/test/, &quot;mytest&quot;); print&#125;&#x27;</span> testfile<br>$ awk <span class="hljs-string">&#x27;&#123;sub(/test/, &quot;mytest&quot;, $1); print&#125;&#x27;</span> testfile<br></code></pre></td></tr></table></figure>

<p>第一个例子在整个记录中匹配，替换只发生在第一次匹配发生的时候。如要在整个文件中进行匹配需要用到 <strong>gsub</strong></p>
<p>第二个例子在整个记录的第一个域中进行匹配，替换只发生在第一次匹配发生的时候。</p>
<ul>
<li><p><strong>gsub</strong> 函数作用如 <strong>sub</strong>，但它在整个文档中进行匹配。格式如下：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">gsub (regular expression, substitution string)<br>gsub (regular expression, substitution string, target string)<br></code></pre></td></tr></table></figure>

<p><strong>实例：</strong></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ awk <span class="hljs-string">&#x27;&#123; gsub(/test/, &quot;mytest&quot;); print &#125;&#x27;</span> testfile<br>$ awk <span class="hljs-string">&#x27;&#123; gsub(/test/, &quot;mytest&quot; , $1) &#125;; print &#125;&#x27;</span> testfile<br></code></pre></td></tr></table></figure>

<p>第一个例子在整个文档中匹配 test，匹配的都被替换成 mytest。</p>
<p>第二个例子在整个文档的第一个域中匹配，所有匹配的都被替换成mytest。</p>
</li>
<li><p><strong>index</strong> 函数返回子字符串第一次被匹配的位置，偏移量从位置1开始。格式如下：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">index(string, substring)<br></code></pre></td></tr></table></figure>

<p>实例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ awk <span class="hljs-string">&#x27;&#123; print index(&quot;test&quot;, &quot;mytest&quot;) &#125;&#x27;</span> testfile<br></code></pre></td></tr></table></figure>

<p>实例返回 test 在 mytest 的位置。</p>
</li>
<li><p><strong>length</strong> 函数返回记录的字符数。格式如下：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">length( string )<br>length<br></code></pre></td></tr></table></figure>

<p>实例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ awk <span class="hljs-string">&#x27;&#123; print length( &quot;test&quot; ) &#125;&#x27;</span> <br>$ awk <span class="hljs-string">&#x27;&#123; print length &#125;&#x27;</span> testfile<br></code></pre></td></tr></table></figure>

<p>第一个实例返回 test 字符串的长度。</p>
<p>第二个实例返回 testfile 文件中<strong>第条记录</strong>的字符数。</p>
</li>
<li><p><strong>substr</strong> 函数返回从位置1开始的子字符串，如果指定长度超过实际长度，就返回整个字符串。格式如下：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">substr( string, starting position )<br>substr( string, starting position, length of string )<br></code></pre></td></tr></table></figure>

<p>实例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ awk <span class="hljs-string">&#x27;&#123; print substr( &quot;hello world&quot;, 7,11 ) &#125;&#x27;</span> <br></code></pre></td></tr></table></figure>

<p>上例截取了 world 子字符串。</p>
</li>
<li><p><strong>match</strong> 函数返回在字符串中正则表达式位置的<strong>索引</strong>，如果找不到指定的正则表达式则返回0。match函数会设置内建变量 <strong>RSTART</strong> 为字符串中子字符串的开始位置，<strong>RLENGTH</strong> 为到子字符串末尾的字符个数。<strong>substr</strong> 可利于这些变量来截取字符串。函数格式如下：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">match( string, regular expression )<br></code></pre></td></tr></table></figure>

<p>实例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ awk <span class="hljs-string">&#x27;&#123;start=match(&quot;this is a test&quot;,/[a-z]+$/); print start&#125;&#x27;</span><br>$ awk <span class="hljs-string">&#x27;&#123;start=match(&quot;this is a test&quot;,/[a-z]+$/); print start, RSTART, RLENGTH &#125;&#x27;</span><br></code></pre></td></tr></table></figure>

<p>第一个实例打印以连续小写字符结尾的开始位置，这里是11。</p>
<p>第二个实例还打印 <strong>RSTART</strong> 和 <strong>RLENGTH</strong> 变量，这里是11(start)，11(RSTART)，4(RLENGTH)。</p>
</li>
<li><p><strong>toupper</strong> 和<strong>tolower</strong> 函数可用于字符串大小间的转换，该功能只在 <strong>gawk</strong> 中有效。格式如下：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">toupper( string )<br>tolower( string )<br></code></pre></td></tr></table></figure>

<p>实例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ awk <span class="hljs-string">&#x27;&#123; print toupper(&quot;test&quot;), tolower(&quot;TEST&quot;) &#125;&#x27;</span><br></code></pre></td></tr></table></figure></li>
<li><p><strong>split</strong> 函数可按给定的分隔符把字符串分割为一个数组。如果分隔符没提供，则按当前 <strong>FS</strong> 值进行分割。格式如下：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">split( string, array, field separator )<br>split( string, array )<br></code></pre></td></tr></table></figure>

<p>实例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ awk <span class="hljs-string">&#x27;&#123; split( &quot;20:18:00&quot;, time, &quot;:&quot; ); print time[2] &#125;&#x27;</span><br></code></pre></td></tr></table></figure>

<p>上例把时间按冒号分割到time数组内，并显示第二个数组元素18。</p>
</li>
</ul>
<h2 id="时间函数"><a href="#时间函数" class="headerlink" title="时间函数"></a>时间函数</h2><ul>
<li><p><strong>systime</strong> 函数返回从1970年1月1日开始到当前时间(不计闰年)的整秒数。格式如下：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">systime()<br></code></pre></td></tr></table></figure>

<p>实例：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ awk <span class="hljs-string">&#x27;&#123; now = systime(); print now &#125;&#x27;</span><br></code></pre></td></tr></table></figure></li>
<li><p><strong>strftime</strong> 函数使用C库中的strftime函数格式化时间。格式如下：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">systime( [format specification][,timestamp] )<br></code></pre></td></tr></table></figure></li>
</ul>
<p>​                                            <strong>日期和时间格式说明符</strong></p>
<table>
<thead>
<tr>
<th>格式</th>
<th>描述</th>
</tr>
</thead>
<tbody><tr>
<td>%a</td>
<td>星期几的缩写(Sun)</td>
</tr>
<tr>
<td>%A</td>
<td>星期几的完整写法(Sunday)</td>
</tr>
<tr>
<td>%b</td>
<td>月名的缩写(Oct)</td>
</tr>
<tr>
<td>%B</td>
<td>月名的完整写法(October)</td>
</tr>
<tr>
<td>%c</td>
<td>本地日期和时间</td>
</tr>
<tr>
<td>%d</td>
<td>十进制日期</td>
</tr>
<tr>
<td>%D</td>
<td>日期 08/20/99</td>
</tr>
<tr>
<td>%e</td>
<td>日期，如果只有一位会补上一个空格</td>
</tr>
<tr>
<td>%H</td>
<td>用十进制表示24小时格式的小时</td>
</tr>
<tr>
<td>%I</td>
<td>用十进制表示12小时格式的小时</td>
</tr>
<tr>
<td>%j</td>
<td>从1月1日起一年中的第几天</td>
</tr>
<tr>
<td>%m</td>
<td>十进制表示的月份</td>
</tr>
<tr>
<td>%M</td>
<td>十进制表示的分钟</td>
</tr>
<tr>
<td>%p</td>
<td>12小时表示法(AM/PM)</td>
</tr>
<tr>
<td>%S</td>
<td>十进制表示的秒</td>
</tr>
<tr>
<td>%U</td>
<td>十进制表示的一年中的第几个星期(星期天作为一个星期的开始)</td>
</tr>
<tr>
<td>%w</td>
<td>十进制表示的星期几(星期天是0)</td>
</tr>
<tr>
<td>%W</td>
<td>十进制表示的一年中的第几个星期(星期一作为一个星期的开始)</td>
</tr>
<tr>
<td>%x</td>
<td>重新设置本地日期(08/20/99)</td>
</tr>
<tr>
<td>%X</td>
<td>重新设置本地时间(12：00：00)</td>
</tr>
<tr>
<td>%y</td>
<td>两位数字表示的年(99)</td>
</tr>
<tr>
<td>%Y</td>
<td>当前月份</td>
</tr>
<tr>
<td>%Z</td>
<td>时区(PDT)</td>
</tr>
<tr>
<td>%%</td>
<td>百分号(%)</td>
</tr>
</tbody></table>
<p><strong>实例：</strong></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ awk <span class="hljs-string">&#x27;&#123; now=strftime( &quot;%D&quot;, systime() ); print now &#125;&#x27;</span><br>$ awk <span class="hljs-string">&#x27;&#123; now=strftime(&quot;%m/%d/%y&quot;); print now &#125;&#x27;</span><br></code></pre></td></tr></table></figure>

<h2 id="内建数学函数"><a href="#内建数学函数" class="headerlink" title="内建数学函数"></a>内建数学函数</h2><table>
<thead>
<tr>
<th>函数名称</th>
<th>返回值</th>
</tr>
</thead>
<tbody><tr>
<td>atan2(x,y)</td>
<td>y,x范围内的余切</td>
</tr>
<tr>
<td>cos(x)</td>
<td>余弦函数</td>
</tr>
<tr>
<td>exp(x)</td>
<td>求幂</td>
</tr>
<tr>
<td>int(x)</td>
<td>取整</td>
</tr>
<tr>
<td>log(x)</td>
<td>自然对数</td>
</tr>
<tr>
<td>rand()</td>
<td>随机数</td>
</tr>
<tr>
<td>sin(x)</td>
<td>正弦</td>
</tr>
<tr>
<td>sqrt(x)</td>
<td>平方根</td>
</tr>
<tr>
<td>srand(x)</td>
<td>x是rand()函数的种子</td>
</tr>
<tr>
<td>int(x)</td>
<td>取整，过程没有舍入</td>
</tr>
<tr>
<td>rand()</td>
<td>产生一个大于等于0而小于1的随机数</td>
</tr>
</tbody></table>
<h2 id="自定义函数"><a href="#自定义函数" class="headerlink" title="自定义函数"></a>自定义函数</h2><p>在 <strong>awk</strong> 中还可自定义函数，格式如下：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-keyword">function</span> name ( parameter, parameter, parameter, ... ) &#123;<br>	statements<br>	<span class="hljs-built_in">return</span> expression	<span class="hljs-comment"># the return statement and expression are optional</span><br>&#125;<br></code></pre></td></tr></table></figure>

<h1 id="实例-1"><a href="#实例-1" class="headerlink" title="实例"></a>实例</h1><ul>
<li><strong>统计nginx 日志单 ip 访问请求数排名钱5名</strong></li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># awk 循环计算，相同IP数量++，最后打印；sort `-n`按照数字排序，`-r`倒序，`-k2` 以第二个域的排序；head -n 5 打印前5条</span><br>$ awk <span class="hljs-string">&#x27;&#123;S[$1]++&#125; END &#123;for(a in S) print a, S[a]&#125;&#x27;</span> <span class="hljs-built_in">log</span>/access.log |sort -rn -k 2 |head -n5<br>192.168.15.66 51<br>192.168.15.77 10<br>192.168.22.65 5<br>192.168.12.48 2<br>192.168.22.36 1<br></code></pre></td></tr></table></figure>

<ul>
<li><strong>统计服务器当前单IP连接数最大的IP地址前十</strong></li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># `netstat -an` 直接显示所有连线中的网络IP地址；`awk -F &#x27;[ :]+&#x27; &#x27;&#123;++S[$6]&#125; END &#123;for (key in S) print &quot;ip:&quot;key&quot;-----&gt;&quot;,S[key]&#125;&#x27;` 循环输出第六个域（Foreign Address）和出现次数；`sort -rn -k2` 对第二个域倒序排序（即对IP出现次数倒序排序）；`head` 默认打印 10 行</span><br>$ netstat -an |grep EST |awk -F <span class="hljs-string">&#x27;[ :]+&#x27;</span> <span class="hljs-string">&#x27;&#123;++S[$6]&#125; END &#123;for (key in S) print &quot;ip:&quot;key&quot;-----&gt;&quot;,S[key]&#125;&#x27;</span> |sort -rn -k2 |head<br>ip:192.168.13.235-----&gt; 69<br>ip:192.168.13.204-----&gt; 66<br>ip:192.168.13.229-----&gt; 21<br>ip:192.168.15.63-----&gt; 5<br>ip:192.168.15.37-----&gt; 5<br>ip:192.168.15.36-----&gt; 4<br>ip:192.168.15.77-----&gt; 2<br></code></pre></td></tr></table></figure>

<ul>
<li><strong>处理以下文件内容,将域名取出并根据域名进行计数排序处理</strong></li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ cat test.log <br>http://www.etiantian.org/index.html<br>http://www.etiantian.org/1.html<br>http://post.etiantian.org/index.html<br>http://mp3.etiantian.org/index.html<br>http://www.etiantian.org/3.html<br>http://post.etiantian.org/2.html<br><span class="hljs-comment"># ①`awk -F &quot;/&quot; &#x27;&#123;print $3&#125;&#x27; test.log`：以‘/’分隔每一行，输出第三个域；`sort` 默认排序；`uniq -c`：报告或忽略文件中的重复行，在每列旁边显示该行重复出现的次数；</span><br>$ awk -F <span class="hljs-string">&quot;/&quot;</span> <span class="hljs-string">&#x27;&#123;print $3&#125;&#x27;</span> test.log |sort |uniq -c <br>1 mp3.etiantian.org<br>2 post.etiantian.org<br>3 www.etiantian.org<br><span class="hljs-comment"># ②`sed &#x27;s#^http://##g&#x27; test.log`：编辑缓冲区，将‘http://’替换为空字符；`sed &#x27;s#/.*##g&#x27;`：将‘/’之后的内容变为空字符；`sort` 默认排序；`uniq -c`：报告或忽略文件中的重复行，在每列旁边显示该行重复出现的次数；</span><br>$ sed <span class="hljs-string">&#x27;s#^http://##g&#x27;</span> test.log|sed <span class="hljs-string">&#x27;s#/.*##g&#x27;</span>|sort |uniq -c<br>	1 mp3.etiantian.org<br>	2 post.etiantian.org<br>	3 www.etiantian.org<br><span class="hljs-comment"># ③以‘/’分隔每行；以第三个域作为数组键值，相同键值++；循环输出数组内容</span><br>$ awk -F <span class="hljs-string">&quot;/&quot;</span> <span class="hljs-string">&#x27;&#123;++S[$3]&#125; END &#123;for(key in S) print S[key],key&#125;&#x27;</span> test.log<br>1 mp3.etiantian.org<br>3 www.etiantian.org<br>2 post.etiantian.org<br><span class="hljs-comment"># ④ 这行命令与方法①类似，关键在于 `-F &#x27;[:/]+&#x27;` 这里的正则所表达的含义</span><br>$ awk -F <span class="hljs-string">&#x27;[:/]+&#x27;</span> <span class="hljs-string">&#x27;&#123;print $2&#125;&#x27;</span> test.log |sort |uniq -c<br>      1 mp3.etiantian.org<br>      2 post.etiantian.org<br>      3 www.etiantian.org<br></code></pre></td></tr></table></figure>










            </div>
            <hr>
            <div>
              <div class="post-metas mb-3">
                
                  <div class="post-meta mr-3">
                    <i class="iconfont icon-category"></i>
                    
                      <a class="hover-with-bg" href="/categories/Shell/">Shell</a>
                    
                  </div>
                
                
                  <div class="post-meta">
                    <i class="iconfont icon-tags"></i>
                    
                      <a class="hover-with-bg" href="/tags/Linux/">Linux</a>
                    
                      <a class="hover-with-bg" href="/tags/Shell/">Shell</a>
                    
                  </div>
                
              </div>
              
                <p class="note note-warning">
                  
                    本博客所有文章除特别声明外，均采用 <a target="_blank" href="https://creativecommons.org/licenses/by-sa/4.0/deed.zh" rel="nofollow noopener noopener">CC BY-SA 4.0 协议</a> ，转载请注明出处！
                  
                </p>
              
              
                <div class="post-prevnext">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/2020/03/26/golang/Golang-%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">Golang-环境搭建</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/2019/05/28/shell/shell-%E6%B5%81%E7%BC%96%E8%BE%91sed/">
                        <span class="hidden-mobile">shell-流编辑sed</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
          </article>
        </div>
      </div>
    </div>
    
      <div class="d-none d-lg-block col-lg-2 toc-container" id="toc-ctn">
        <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;目录</p>
  <div class="toc-body" id="toc-body"></div>
</div>

      </div>
    
  </div>
</div>

<!-- Custom -->


    

    
      <a id="scroll-top-button" aria-label="TOP" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>
    

    
      <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v"
                 for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>
    

    
  </main>

  <footer class="text-center mt-5 py-3">
  <div class="footer-content">
     <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a> <i class="iconfont icon-love"></i> <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener"><span>Fluid</span></a> 
  </div>
  

  

  
</footer>


  <!-- SCRIPTS -->
  
  <script  src="https://cdn.jsdelivr.net/npm/nprogress@0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/nprogress@0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":false,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js" ></script>
<script  src="https://cdn.jsdelivr.net/npm/bootstrap@4/dist/js/bootstrap.min.js" ></script>
<script  src="/js/events.js" ></script>
<script  src="/js/plugins.js" ></script>

<!-- Plugins -->


  <script  src="/js/local-search.js" ></script>



  
    <script  src="/js/img-lazyload.js" ></script>
  



  



  
    <script  src="https://cdn.jsdelivr.net/npm/tocbot@4/dist/tocbot.min.js" ></script>
  
  
    <script  src="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3/dist/jquery.fancybox.min.js" ></script>
  
  
    <script  src="https://cdn.jsdelivr.net/npm/anchor-js@4/anchor.min.js" ></script>
  
  
    <script defer src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js" ></script>
  






  <script  src="https://cdn.jsdelivr.net/npm/typed.js@2/lib/typed.min.js" ></script>
  <script>
    (function (window, document) {
      var typing = Fluid.plugins.typing;
      var title = document.getElementById('subtitle').title;
      
        typing(title);
      
    })(window, document);
  </script>















<!-- 主题的启动项 保持在最底部 -->
<script  src="/js/boot.js" ></script>


</body>
</html>
